package com.chase.passwordmaster.mine.export

import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.os.Environment
import android.view.View
import android.widget.EditText
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.ViewModelProviders
import com.chase.passwordmaster.R
import com.chase.passwordmaster.data.AccountViewModel
import com.chase.passwordmaster.entity.DecryptedAccount
import com.chase.passwordmaster.utils.*
import java.io.File
import java.io.IOException
import java.lang.Exception
import java.lang.IllegalArgumentException
import java.lang.RuntimeException

class ImportActivity : AppCompatActivity() {
    companion object {
        fun actionStart(context: Context) {
            val intent = Intent(context, ImportActivity::class.java)
            context.startActivity(intent)
        }
    }

    private lateinit var accountViewModel: AccountViewModel

    private lateinit var cpBack: View
    private lateinit var cpImportCleartextCover: View
    private lateinit var cpImportCleartextMerge: View
    private lateinit var cpImportRSACover: View
    private lateinit var cpImportRSAMerge: View
    private lateinit var cpPrivateKey: EditText

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_import)

        accountViewModel = ViewModelProviders.of(this).get(AccountViewModel::class.java)

        cpBack = findViewById(R.id.back_import)
        cpImportCleartextCover = findViewById(R.id.import_cover_cleartext_import)
        cpImportCleartextMerge = findViewById(R.id.import_merge_cleartext_import)
        cpImportRSACover = findViewById(R.id.import_cover_rsa_import)
        cpImportRSAMerge = findViewById(R.id.import_merge_rsa_import)
        cpPrivateKey = findViewById(R.id.private_key_import)

        useDarkStatusBar()
        useImmersingNavigator()

        initCPBack()
        initCPImportCleartext()
        initCPImportRSA()
    }

    /**
     * Decrypted ExternalDecryptedAccount encrypted by RSA into ExternalDecryptedAccount without encryption of RSA
     */
    private fun decryptExternalAccountByRSA(
        account: ExternalDecryptedAccount,
        privateKeyString: String
    ) =
        account.run {
            ExternalDecryptedAccount(
                website,
                decryptByRSA(username, privateKeyString),
                decryptByRSA(password, privateKeyString),
                name?.let { decryptByRSA(it, privateKeyString) },
                tel?.let { decryptByRSA(it, privateKeyString) },
                qq?.let { decryptByRSA(it, privateKeyString) },
                weChat?.let { decryptByRSA(it, privateKeyString) },
                email?.let { decryptByRSA(it, privateKeyString) },
                memo
            )
        }

    /**
     * Cover listener
     */
    private fun coverListener(
        filePath: String,
        importCallback: (List<ExternalDecryptedAccount>) -> Unit
    ) {
        fun recover(backupList: ArrayList<DecryptedAccount>) {
            val recordSize = accountViewModel.getRecordSizeInDB()
            if (recordSize != backupList.size || recordSize == 0) {
                backupList.forEach { it.save() }
            }
            accountViewModel.getAccountLiveData().value = backupList
        }

        // Check file exists or not
        try {
            val json = File(filePath).readText()
            AlertDialog.Builder(this)
                .setTitle("覆盖导入将会删除现有的数据")
                .setPositiveButton("覆盖导入") { dialog, which ->
                    // Back up current accountList in AccountViewModel's liveData
                    val backupAccountList = accountViewModel.getAccountLiveData().value

                    try {
                        val externalAccountList = importExternalAccountList(json)
                        accountViewModel.removeAll()
                        // Run callback
                        importCallback(externalAccountList)
                    } catch (e: Exception) {
                        // If throw exception, try to recover data
                        accountViewModel.getAccountLiveData().value?.let {
                            if (it.size == 0) {
                                // Recover
                                backupAccountList?.let { recover(it) }
                            }
                        } ?: run {
                            // Recover
                            backupAccountList?.let { recover(it) }
                        }

                        // Print and write out crash log, throw exception
                        Logger.e("Cover import Exception", e.getContent())
                        e.printStackTrace()
                        throw e
                    }
                }
                .setNegativeButton("取消") { dialog, which ->
                    dialog.cancel()
                }
                .show()
        } catch (e: IOException) {
            // External json file not found
            showToast("未找到\n${ExportActivity.EXPORT_DIR}/${ExportActivity.EXPORT_CLEARTEXT_FILE_NAME}\n导入失败")
        }
    }

    /**
     * Merge listener
     */
    private fun mergeListener(
        filePath: String,
        importCallback: (List<ExternalDecryptedAccount>) -> Unit
    ) {
        try {
            val json =
                File(filePath).readText()

            AlertDialog.Builder(this)
                .setTitle("合并导入仅追加，不会查重")
                .setPositiveButton("合并导入") { dialog, which ->
                    val externalAccountList = importExternalAccountList(json)
                    // Run callback
                    importCallback(externalAccountList)
                }
                .setNegativeButton("取消") { dialog, which ->
                    dialog.cancel()
                }
                .show()
        } catch (e: IOException) {
            // External json file not found
            showToast("未找到\n${ExportActivity.EXPORT_DIR}/${ExportActivity.EXPORT_CLEARTEXT_FILE_NAME}\n导入失败")
        }
    }


    private fun initCPImportRSA() {
        cpImportRSACover.setOnClickListener {
            val privateKeyString = cpPrivateKey.text.toString()
            if (!isValidPrivateKey(privateKeyString)) {
                showToast("RSA 密钥不合法")
                return@setOnClickListener
            }
            coverListener("${Environment.getExternalStorageDirectory().absolutePath}/${ExportActivity.EXPORT_DIR}/${ExportActivity.EXPORT_ENCRYPTED_FILE_NAME}") {
                try {
                    it.forEach {
                        accountViewModel.addAccount(
                            decryptExternalAccountByRSA(
                                it,
                                privateKeyString
                            ).toDecryptedAccount()
                        )
                    }
                    AlertDialog.Builder(this)
                        .setTitle("覆盖导入成功")
                        .setPositiveButton("确定") { dialog, which ->
                            dialog.cancel()
                        }
                        .show()
                } catch (e: IllegalArgumentException) {
                    Logger.e("Decrypt external account by rsa in ImportActivity", e.getContent())
                    showToast("待导入文件损坏")
                    e.printStackTrace()
                } catch (e: RuntimeException) {
                    Logger.e("Decrypt external account by rsa in ImportActivity", e.getContent())
                    showToast("RSA 私钥与加密待导入文件的公钥不匹配")
                    e.printStackTrace()
                } catch (e: Exception) {
                    Logger.e("Decrypt external account by rsa in ImportActivity", e.getContent())
                    e.printStackTrace()
                    throw e
                }
            }
        }
        cpImportRSAMerge.setOnClickListener {
            val privateKeyString = cpPrivateKey.text.toString()
            if (!isValidPrivateKey(privateKeyString)) {
                showToast("RSA 密钥不合法")
                return@setOnClickListener
            }
            mergeListener("${Environment.getExternalStorageDirectory().absolutePath}/${ExportActivity.EXPORT_DIR}/${ExportActivity.EXPORT_ENCRYPTED_FILE_NAME}") {
                try {
                    it.forEach {
                        accountViewModel.addAccount(
                            decryptExternalAccountByRSA(
                                it,
                                privateKeyString
                            ).toDecryptedAccount()
                        )
                    }

                    AlertDialog.Builder(this)
                        .setTitle("合并导入成功")
                        .setPositiveButton("确定") { dialog, which ->
                            dialog.cancel()
                        }
                        .show()
                } catch (e: IllegalArgumentException) {
                    Logger.e("Decrypt external account by rsa in ImportActivity", e.getContent())
                    showToast("RSA 密钥不匹配或待导入文件损坏")
                    e.printStackTrace()
                } catch (e: RuntimeException) {
                    Logger.e("Decrypt external account by rsa in ImportActivity", e.getContent())
                    showToast("RSA 私钥与加密待导入文件的公钥不匹配")
                    e.printStackTrace()
                } catch (e: Exception) {
                    Logger.e("Decrypt external account by rsa in ImportActivity", e.getContent())
                    e.printStackTrace()
                    throw e
                }
            }
        }
    }

    private fun initCPImportCleartext() {
        cpImportCleartextCover.setOnClickListener {
            coverListener("${Environment.getExternalStorageDirectory().absolutePath}/${ExportActivity.EXPORT_DIR}/${ExportActivity.EXPORT_CLEARTEXT_FILE_NAME}") {
                it.forEach {
                    accountViewModel.addAccount(it.toDecryptedAccount())
                }
                AlertDialog.Builder(this)
                    .setTitle("覆盖导入成功")
                    .setPositiveButton("确定") { dialog, which ->
                        dialog.cancel()
                    }
                    .show()
            }
        }

        cpImportCleartextMerge.setOnClickListener {
            mergeListener("${Environment.getExternalStorageDirectory().absolutePath}/${ExportActivity.EXPORT_DIR}/${ExportActivity.EXPORT_CLEARTEXT_FILE_NAME}") {
                it.forEach {
                    accountViewModel.addAccount(it.toDecryptedAccount())
                }
                AlertDialog.Builder(this)
                    .setTitle("合并导入成功")
                    .setPositiveButton("确定") { dialog, which ->
                        dialog.cancel()
                    }
                    .show()
            }
        }
    }

    private fun initCPBack() {
        cpBack.setOnClickListener { onBackPressed() }
    }
}

